package cn.apotato.modules.mybatis.plus.plungs;

import cn.apotato.modules.mybatis.plus.model.TenantInfo;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 我房客线处理程序
 *
 * @author 胡晓鹏
 * @date 2023/05/19
 */
public class MyTenantLineHandler implements TenantLineHandler {
    private final TenantInfo tenantInfo;

    public MyTenantLineHandler(TenantInfo tenantInfo) {
        this.tenantInfo = tenantInfo;
    }

    /**
     * 获取租户 ID 值表达式，只支持单个 ID 值
     * 获取租户 ID 的方式有多种,这里要看程序的多租户的方式;
     * - 如果是单独部署的方式可以通过激活码/环境变量等方式进行传递。
     * - 若果是线上的同一个程序就需要通过创账户时分配给root账户的租户ID来确定
     * @return 租户 ID 值表达式
     */
    @Override
    public Expression getTenantId() {
        String tenantId = "1";
        if (tenantInfo != null) {
            tenantId = tenantInfo.getTenantId();
        }
        return new StringValue(tenantId);
    }

    /**
     * 获取租户字段名
     * <p>
     * 默认字段名叫: tenant_id
     *
     * @return 租户字段名
     */
    @Override
    public String getTenantIdColumn() {
        // 如果该字段你不是固定的，请使用 SqlInjectionUtils.check 检查安全性
        String tenantIdColumn = tenantInfo.getTenantIdColumn();
        if (StringUtils.isNotBlank(tenantIdColumn) && SqlInjectionUtils.check(tenantIdColumn)) {
            return tenantIdColumn;
        }
        return "org_id";
    }

    /**
     * 忽略表
     * 这是 default 方法,默认返回 false 表示所有表都需要拼多租户条件
     * @param tableName 表名
     * @return boolean
     */
    @Override
    public boolean ignoreTable(String tableName) {
        List<String> ignoreTable = tenantInfo.getIgnoreTable();
        if (ignoreTable != null && ignoreTable.size() > 0) {
            List<String> collect = ignoreTable.stream()
                    .filter(Objects::nonNull)
                    .map(String::toLowerCase).collect(Collectors.toList());
            return collect.contains(tableName.toLowerCase());
        }
        return false;
    }
}
